const {
    clear_line,
    clear_line_end,
    OPTION_PAGE_SIZE,
    shareData,
    LINE_EXPRESSION,
} = require("../commands/share_data");
const {
    whisper,
    warn,
    info,
    log,
    omit,
    omit_offset,
    write,
} = require("./log_tool");
const { alignStr, alignNumber, Alignment } = require("./transform_tool");

function moveCursorLineUp(n) {
    write(`\x1B[${n}A\r`);
}

function clearLine() {
    if (shareData.FULL_AUTOMATIC) {
        return;
    }
    // write(clear_line);
    process.stdout.clearLine(0);
}

function toggleRawMode(flag) {
    if (shareData.FULL_AUTOMATIC) {
        return;
    }
    if (typeof process.stdin.setRawMode === "function") {
        process.stdin.setRawMode(flag);
    } else {
        if (typeof tty === "object") {
            tty.setRawMode(flag);
        }
    }
}

/**
 *
 * @param {*} prompt
 * @param {number} countdown 自动倒计时(秒数)
 */
async function pause(prompt = "", countdown) {
    if (shareData.FULL_AUTOMATIC) {
        return;
    }
    const needCountDown = countdown > 0;
    let leftTime = countdown;
    log("");
    if (needCountDown) {
        warn(`${prompt} ... [回车键继续 ${leftTime}s] `);
    } else {
        warn(`${prompt} ... [回车键继续] `);
    }
    await new Promise((resolve) => {
        process.stdin.on("keypress", onKeyPress);
        toggleRawMode(true);
        process.stdin.resume();
        function onKeyPress(_ch, key) {
            const _isKey = false;
            const _inputsChg = false;
            if (key) {
                if (key.name === "return") {
                    moveCursorLineUp(1);
                    willResolve();
                } else if (key.ctrl && key.name === "c") {
                    throw "用户中止";
                    return;
                } else {
                    clearInterval(timeout);
                    moveCursorLineUp(1);
                    warn(`${prompt} ... [回车键继续]  ${clear_line_end}`);
                }
            }
        }
        let timeout = 0;
        if (needCountDown) {
            timeout = setInterval(() => {
                leftTime -= 1;
                moveCursorLineUp(1);
                warn(`${prompt} ... [回车键继续 ${leftTime}s] `);
                if (leftTime <= 0) {
                    willResolve();
                }
            }, 1000);
        }

        function willResolve() {
            clearInterval(timeout);
            process.stdin.off("keypress", onKeyPress);
            process.stdin.pause();
            resolve();
        }
    });
}

/** 记录上一个显示的选项 */
let prevViewOptions = null;
let prevBegIndex = 0;
let prevFocusIndex = 0;
let firstTime = true;

function resetOptions() {
    prevViewOptions = null;
    prevBegIndex = 0;
    prevFocusIndex = 0;
    firstTime = true;
}

/**
 *
 * @param {{key: string, value: any}[]} viewOptions
 * @param {{key: string, value: any}[]} filteredViewOptions
 * @param {*} selectedIndices
 * @param {number} focusedIndex
 * @param {number} numPerPage
 */
function showOptions(
    viewOptions,
    filteredViewOptions,
    selectedIndices,
    focusedIndex = -1,
    numPerPage = OPTION_PAGE_SIZE,
    indicator_char = ">",
    searchChars = "",
) {
    const selectColor = "green"; // 选中颜色
    const focusColor = "gray"; // 焦点颜色
    const filterColor = "reset"; // 筛选颜色
    const defaultColor = "gray"; // 默认颜色
    let begIndex = 0;
    const numShow = Math.min(
        filteredViewOptions.length,
        numPerPage > 0 ? numPerPage : filteredViewOptions.length,
    );
    // 转换成filterdView
    focusedIndex = filteredViewOptions.indexOf(viewOptions[focusedIndex]);
    if (typeof selectedIndices === "number") {
        selectedIndices = filteredViewOptions.indexOf(
            viewOptions[selectedIndices],
        );
    } else {
        selectedIndices = selectedIndices
            .concat()
            .map((v) => filteredViewOptions.indexOf(viewOptions[v]));
    }
    if (prevViewOptions?.every((v, i) => v === filteredViewOptions[i])) {
        prevViewOptions = filteredViewOptions;
        begIndex = prevBegIndex = 0;
        prevFocusIndex = 0;
    } else {
        const focusOffset = focusedIndex - prevFocusIndex;
        const isPageDown = focusOffset >= numPerPage;
        const isPageUp = focusOffset <= -numPerPage;
        if (isPageDown) {
            begIndex = Math.min(
                focusedIndex,
                filteredViewOptions.length - numShow,
            );
        } else if (isPageUp) {
            begIndex = Math.max(0, focusedIndex - numPerPage);
        } else {
            begIndex = prevBegIndex;
        }
        if (firstTime) {
            firstTime = false;
        } else {
            moveCursorLineUp(numPerPage + 4);
        }
    }
    // 需要对begIndex进行限制
    if (focusedIndex !== -1) {
        // 超出单页显示，要修正
        if (focusedIndex < begIndex) {
            begIndex = focusedIndex;
        } else if (focusedIndex >= begIndex + numShow) {
            begIndex = Math.min(
                filteredViewOptions.length - numShow,
                focusedIndex - numShow + 1,
            );
        }
    }
    prevBegIndex = begIndex;
    prevFocusIndex = focusedIndex;
    let alignment = Alignment.RIGHT;
    const maxKeyLength = filteredViewOptions.reduce((prev, current) => {
        if (
            alignment === Alignment.RIGHT &&
            Number.isNaN(parseInt(current.key, 10))
        ) {
            alignment = Alignment.LEFT;
        }
        return Math.max(prev, current.key.toString().length);
    }, 0);
    clearLine();
    info(
        `当前选择: ${typeof selectedIndices === "number" ? (selectedIndices === -1 ? 0 : 1) : selectedIndices.length} / ${filteredViewOptions.length}`,
    );
    write(`${begIndex === 0 ? "" : "▲".magenta}${clear_line_end}\n`);
    for (let i = 0; i < numPerPage; ++i) {
        // for (let index = begIndex; index < begIndex + numShow; index++) {
        const index = begIndex + i;
        const viewOption = filteredViewOptions[index];
        if (viewOption === undefined) {
            write(`${clear_line_end}\n`);
            continue;
        }
        const viewOptionStr = `${alignStr(viewOption.showKey, maxKeyLength, { alignment: alignment })} - ${viewOption.value?.toString().replace(new RegExp(LINE_EXPRESSION, "g"), "")}`;
        let indicator;
        let optionColor;
        const selected =
            selectedIndices === index ||
            (Array.isArray(selectedIndices) && selectedIndices.includes(index));
        const focused = focusedIndex === index;
        const filtered =
            filteredViewOptions &&
            filteredViewOptions.length !== filteredViewOptions.length &&
            filteredViewOptions.includes(viewOption);
        indicator = focused ? `${indicator_char} `[selectColor] : "  ";
        if (selected) {
            optionColor = selectColor;
        } else if (filtered) {
            optionColor = filterColor;
        } else if (focused) {
            optionColor = focusColor;
        } else {
            optionColor = defaultColor;
        }
        // 清空本行
        clearLine();
        let preview = omit_offset(viewOptionStr, 2);
        const previewParts = preview.split(searchChars);
        preview = previewParts
            .map((v) => v[optionColor])
            .join(searchChars.bold);
        write(`${indicator}${preview}`);
        write("\n");
    }
    write(
        `${begIndex + numShow >= filteredViewOptions.length ? "" : "▼".magenta}${clear_line_end}\n`,
    );
}

module.exports = {
    moveCursorLineUp,
    toggleRawMode,
    pause,
    showOptions,
    resetOptions,
    clearLine,
};
